﻿using ApiLib.AppStart;
using ApiLib.Utils;
using CSRedis;

namespace ApiLib.Helpers;

/// <summary>
/// Redis缓存
/// </summary>
public static class RedisCache
{
    /// <summary>
    /// 使用Redis
    /// </summary>
    public static bool UseRedis =>
        GlobalConfig.AppConfig != null && GlobalConfig.AppConfig.Redis.IsNotNullOrEmpty();
    
    /// <summary>
    /// 初始化
    /// </summary>
    public static void Init()
    {
        if (UseRedis)
        {
            RedisHelper.Initialization(new CSRedisClient(GlobalConfig.AppConfig.Redis));
            WebUtil.LogSys("初始化Redis成功");
        }
    }
    
    #region 基础方法

    /// <summary>
    /// 设置有效时间
    /// </summary>
    /// <param name="key">Redis键</param>
    /// <param name="timeout">超时时间</param>
    /// <returns>true=设置成功；false=设置失败</returns>
    public static bool Expire(string key, int timeout)
    {
        return RedisHelper.Expire(key, timeout);
    }

    /// <summary>
    /// 判断key是否存在
    /// </summary>
    /// <param name="key">键</param>
    /// <returns>true 存在 false不存在</returns>
    public static bool HasKey(string key)
    {
        return RedisHelper.Exists(key);
    }

    /// <summary>用于在 key 存在时删除 key</summary>
    /// <param name="key">不含prefix前辍</param>
    /// <returns></returns>
    public static long Del(params string[] key)
    {
        return RedisHelper.Del(key);
    }

    #endregion

    #region 单个对象

    /// <summary>
    /// 缓存基本的对象，Integer、String、实体类等
    /// </summary>
    /// <param name="key">缓存的键值</param>
    /// <param name="value">缓存的值</param>
    /// <param name="expire">时间:秒,小于等于0不会过期</param>
    public static void Set(string key, object value, int expire = -1)
    {
        RedisHelper.Set(key, value, expire);
    }
    /// <summary>
    /// 缓存基本的对象，Integer、String、实体类等
    /// </summary>
    /// <param name="key">缓存的键值</param>
    /// <param name="value">缓存的值</param>
    /// <param name="expire">时间:秒</param>
    public static async Task<bool> SetAsync(string key, object value, int expire = -1)
    {
        return await RedisHelper.SetAsync(key, value, expire);
    }

    /// <summary>
    /// 获得缓存的基本对象。
    /// </summary>
    /// <param name="key">缓存键值</param>
    /// <returns></returns>
    public static string Get(string key)
    {
        return RedisHelper.Get(key);
    }

    /// <summary>
    /// 获得缓存的基本对象。
    /// </summary>
    /// <param name="key">缓存键值</param>
    /// <typeparam name="T">缓存键值对应的数据</typeparam>
    /// <returns></returns>
    public static T? Get<T>(string key)
    {
        if (UseRedis)
        {
            return RedisHelper.Get<T>(key);
        }

        return default;
    }

    #endregion

    #region List

    /// <summary>
    /// 缓存List数据
    /// </summary>
    /// <param name="key">缓存的键值</param>
    /// <param name="index">索引</param>
    /// <param name="data"></param>
    /// <returns></returns>
    public static bool LSet(string key, int index, object data)
    {
        return RedisHelper.LSet(key,index, data);
    }
    /// <summary>
    /// 缓存List数据
    /// </summary>
    /// <param name="key">缓存的键值</param>
    /// <param name="dataList">待缓存的List数据</param>
    /// <typeparam name="T">缓存的对象</typeparam>
    /// <returns></returns>
    public static long LPush<T>(string key, params T[] dataList)
    {
        return RedisHelper.LPush(key, dataList);
    }

    /// <summary>通过索引设置列表元素的值</summary>
    /// <param name="key">不含prefix前辍</param>
    /// <param name="index">索引</param>
    /// <param name="value">值</param>
    /// <returns></returns>
    public static bool LSet(string key, long index, object value)
    {
        return RedisHelper.LSet(key, index, value);
    }

    /// <summary>
    /// 获得缓存的list对象
    /// </summary>
    /// <param name="key">缓存的键值</param>
    /// <typeparam name="T">缓存键值对应的数据</typeparam>
    /// <returns></returns>
    public static T[] LGet<T>(string key)
    {
        return RedisHelper.LRange<T>(key, 0, -1);
    }

    /// <summary>
    /// 获得缓存的list对象
    /// </summary>
    /// <param name="key">缓存的键值</param>
    /// <returns></returns>
    public static string[] LGet(string key)
    {
        return RedisHelper.LRange(key, 0, -1);
    }

    /// <summary>根据参数 count 的值，移除列表中与参数 value 相等的元素</summary>
    /// <param name="key">不含prefix前辍</param>
    /// <param name="count">移除的数量，大于0时从表头删除数量count，小于0时从表尾删除数量-count，等于0移除所有</param>
    /// <param name="value">元素</param>
    /// <returns></returns>
    public static long LDel(string key, long count, object value)
    {
        return RedisHelper.LRem(key, count, value);
    }

    #endregion
    
    #region Set不重复列表

    /// <summary>
    /// 缓存Set
    /// </summary>
    /// <param name="key">缓存键值</param>
    /// <param name="dataSet">缓存的数据</param>
    /// <typeparam name="T">缓存数据的对象</typeparam>
    /// <returns></returns>
    public static long SSet<T>(string key, params T[] dataSet)
    {
        return RedisHelper.SAdd(key, dataSet);
    }

    /// <summary>返回集合中的所有成员</summary>
    /// <typeparam name="T">byte[] 或其他类型</typeparam>
    /// <param name="key">不含prefix前辍</param>
    /// <returns></returns>
    public static T[] SGet<T>(string key)
    {
        return RedisHelper.SMembers<T>(key);
    }

    /// <summary>返回集合中的所有成员</summary>
    /// <param name="key">不含prefix前辍</param>
    /// <returns></returns>
    public static string[] SGet(string key)
    {
        return RedisHelper.SMembers(key);
    }

    /// <summary>移除集合中一个或多个成员</summary>
    /// <param name="key">不含prefix前辍</param>
    /// <param name="members">一个或多个成员</param>
    /// <returns></returns>
    public static long SDel<T>(string key, params T[] members)
    {
        return RedisHelper.SRem(key, members);
    }

    /// <summary>判断 member 元素是否是集合 key 的成员</summary>
    /// <param name="key">不含prefix前辍</param>
    /// <param name="member">成员</param>
    /// <returns></returns>
    public static bool SIsMember(string key, object member)
    {
        return RedisHelper.SIsMember(key, member);
    }

    #endregion
    
    #region Hash字典

    /// <summary>同时将多个 field-value (域-值)对设置到哈希表 key 中</summary>
    /// <param name="key">不含prefix前辍</param>
    /// <param name="dataMap">字典</param>
    /// <returns></returns>
    public static void HSet<T>(string key, Dictionary<string, T> dataMap)
    {
        var keyValues = new List<object>();
        foreach (var (s, value) in dataMap)
        {
            if (value == null) continue;
            keyValues.Add(s);
            keyValues.Add(value);
        }

        RedisHelper.HMSet(key, keyValues.ToArray());
    }

    /// <summary>将哈希表 key 中的字段 field 的值设为 value</summary>
    /// <param name="key">不含prefix前辍</param>
    /// <param name="field">字段</param>
    /// <param name="value">值</param>
    /// <returns>如果字段是哈希表中的一个新建字段，并且值设置成功，返回true。如果哈希表中域字段已经存在且旧值已被新值覆盖，返回false。</returns>
    public static void HSet<T>(string key, string field, T value)
    {
        RedisHelper.HSet(key, field, value);
    }

    /// <summary>获取在哈希表中指定 key 的所有字段和值</summary>
    /// <typeparam name="T">byte[] 或其他类型</typeparam>
    /// <param name="key">不含prefix前辍</param>
    /// <returns></returns>
    public static Dictionary<string, T> HGet<T>(string key)
    {
        return RedisHelper.HGetAll<T>(key);
    }

    /// <summary>获取在哈希表中指定 key 的所有字段和值</summary>
    /// <param name="key">不含prefix前辍</param>
    /// <returns></returns>
    public static Dictionary<string, string> HGet(string key)
    {
        return RedisHelper.HGetAll(key);
    }

    /// <summary>获取存储在哈希表中指定字段的值</summary>
    /// <typeparam name="T">byte[] 或其他类型</typeparam>
    /// <param name="key">不含prefix前辍</param>
    /// <param name="field">字段</param>
    /// <returns></returns>
    public static T HGet<T>(string key, string field)
    {
        return RedisHelper.HGet<T>(key, field);
    }

    /// <summary>获取存储在哈希表中指定字段的值</summary>
    /// <param name="key">不含prefix前辍</param>
    /// <param name="field">字段</param>
    /// <returns></returns>
    public static string HGet(string key, string field)
    {
        return RedisHelper.HGet(key, field);
    }

    /// <summary>获取存储在哈希表中多个字段的值</summary>
    /// <typeparam name="T">byte[] 或其他类型</typeparam>
    /// <param name="key">不含prefix前辍</param>
    /// <param name="fields">一个或多个字段</param>
    /// <returns></returns>
    public static List<T> HGetValues<T>(string key, params string[] fields)
    {
        return RedisHelper.HMGet<T>(key, fields).ToList();
    }

    /// <summary>删除一个或多个哈希表字段</summary>
    /// <param name="key">不含prefix前辍</param>
    /// <param name="fields">字段</param>
    /// <returns></returns>
    public static long HDel(string key, params string[] fields)
    {
        return RedisHelper.HDel(key, fields);
    }

    /// <summary>获取所有哈希表中的字段</summary>
    /// <param name="key">不含prefix前辍</param>
    /// <returns></returns>
    public static string[] HKeys(string key)
    {
        return RedisHelper.HKeys(key);
    }

    /// <summary>查看哈希表 key 中，指定的字段是否存在</summary>
    /// <param name="key">不含prefix前辍</param>
    /// <param name="field">字段</param>
    /// <returns></returns>
    public static bool HExists(string key, string field)
    {
        return RedisHelper.HExists(key, field);
    }

    #endregion
}